import requests
import time
import hmac
import hashlib
import base64
import urllib.parse
import logging
from typing import Optional, Dict, Any

logger = logging.getLogger(__name__)

class DingTalkRobotSender:
    """钉钉机器人消息发送器"""
    
    def __init__(self, webhook: str, secret: Optional[str] = None):
        """
        初始化钉钉机器人发送器
        :param webhook: 钉钉机器人的webhook地址
        :param secret: 钉钉机器人的签名密钥（可选）
        """
        self.webhook = webhook
        self.secret = secret
    
    def send_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """
        发送消息到钉钉机器人
        :param message: 消息内容，格式为钉钉消息格式
        :return: 发送结果，包含errcode和errmsg
        """
        try:
            # 构建请求URL
            url = self.webhook
            
            # 如果有签名密钥，添加签名
            if self.secret:
                timestamp = str(round(time.time() * 1000))
                # 使用与定时任务相同的签名计算方法
                string_to_sign = f"{timestamp}\n{self.secret}"
                string_to_sign_enc = string_to_sign.encode('utf-8')
                secret_enc = self.secret.encode('utf-8')
                hmac_code = hmac.new(secret_enc, string_to_sign_enc, digestmod=hashlib.sha256).digest()
                sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
                url = f"{self.webhook}&timestamp={timestamp}&sign={sign}"
            
            # 发送请求
            headers = {'Content-Type': 'application/json'}
            response = requests.post(url, headers=headers, json=message, timeout=10)
            
            # 检查响应
            if response.status_code != 200:
                return {
                    'errcode': -1,
                    'errmsg': f'HTTP请求失败: {response.status_code}'
                }
            
            result = response.json()
            return result
            
        except requests.exceptions.Timeout:
            return {
                'errcode': -1,
                'errmsg': '请求超时'
            }
        except requests.exceptions.RequestException as e:
            return {
                'errcode': -1,
                'errmsg': f'网络请求错误: {str(e)}'
            }
        except Exception as e:
            logger.error(f"发送钉钉消息失败: {str(e)}")
            return {
                'errcode': -1,
                'errmsg': f'发送失败: {str(e)}'
            }
    
    def send_text(self, content: str) -> Dict[str, Any]:
        """
        发送文本消息
        :param content: 文本内容
        :return: 发送结果
        """
        message = {
            "msgtype": "text",
            "text": {
                "content": content
            }
        }
        return self.send_message(message)
    
    def send_markdown(self, title: str, content: str) -> Dict[str, Any]:
        """
        发送markdown消息
        :param title: 标题
        :param content: markdown内容
        :return: 发送结果
        """
        message = {
            "msgtype": "markdown",
            "markdown": {
                "title": title,
                "text": content
            }
        }
        return self.send_message(message)
    
    def send_link(self, title: str, text: str, pic_url: str = "", message_url: str = "") -> dict:
        """
        发送链接消息
        :param title: 标题
        :param text: 文本内容
        :param pic_url: 图片URL（可选）
        :param message_url: 点击跳转的URL
        :return: 发送结果
        """
        message = {
            "msgtype": "link",
            "link": {
                "title": title,
                "text": text,
                "picUrl": pic_url,
                "messageUrl": message_url
            }
        }
        return self.send_message(message)